from __future__ import absolute_import
import logging
import subprocess
import os
from forest.registry import register_tool
from forest.tool import Tool

logger = logging.getLogger('forest.tools.system.Execute')


from forest.tools.system.which import require_executable


@register_tool('system.process')
def process(exe):
    ''' Executes a command in the install_root '''
    try:
        exe[0] = require_executable(exe[0])
        logger.debug('process: %s' % exe)
        p = subprocess.Popen(exe, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=os.getcwd()) # shell=True,
        return p
    except Exception, e:
        print e
        raise



@register_tool('system.execute')
def run(exe, expected=None, root=None):
    ''' Executes a command in the install_root '''

    if root is not None:
        cwd = root
        def chroot():
            os.chroot(root)
    else:
        cwd = os.getcwd()
        def chroot():
            pass


    try:
        env = os.environ.copy()
        env.update({"LC_ALL": "C", "PATH":'{}'.format(os.pathsep).join(['/bin', '/sbin', '/usr/bin', '/usr/sbin'])})
        exe[0] = require_executable(exe[0])

        logger.debug('Run: %s' % exe)

        p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=chroot, cwd=cwd, env=env)

        #output, errors = p.communicate()
        p.communicate()

        if expected:
            if p.returncode not in expected:
                raise Exception("Unexpected return code from %s: %s" % (' '.join(exe), p.returncode))

        return p.returncode
    except Exception, e:
        print 'Execute had the following exception:'
        print e
        raise


@register_tool('system.poll')
def poll(exe, shell=False):
    ''' Executes a command in the install_root '''
    #this polling doesn't seem to work. but instead of a bugfix, writing another fn
    #since failry different - and maybe there's a more similar approach to this
    #structure
    try:
        env = os.environ.copy()
        env.update({"LC_ALL": "C", "PATH":'{}'.format(os.pathsep).join(['/bin', '/sbin', '/usr/bin', '/usr/sbin'])})
        exe[0] = require_executable(exe[0])

        logger.info('Polling: %s' % exe)

        # stdin=subprocess.PIPE,
        # env=os.environ
        p = subprocess.Popen(exe,
            bufsize=1, # line buffered (default)
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, cwd=os.getcwd(), env=env)

        while True:
            p.poll()
            line = p.stdout.readline()
            eline = p.stderr.readline()
            if line:
                yield False, line
            if eline:
                yield True, eline
            if (line == "" and eline == "" and p.returncode != None):
                break

    except Exception, e:
        print e
        raise

@register_tool('system.spoll')
def spoll(exe, shell=False):
    '''simpler rewrite of spoll, not using readline()-s'''
    try:
        env = os.environ.copy()
        env.update({"LC_ALL": "C", "PATH":'{}'.format(os.pathsep).join(['/bin', '/sbin', '/usr/bin', '/usr/sbin'])})
        exe[0] = require_executable(exe[0])

        logger.info('Simple polling: %s' % exe)
        p = subprocess.Popen(exe,
            bufsize=1, # line buffered (default)
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, cwd=os.getcwd(), env=env)
        p.poll()
        if p.stdout:
            for line in p.stdout:
                yield False, line
        if p.stderr:
            for eline in p.stderr:
                yield True, eline
        Tool.SIGNAL_TOOL_FINISH(spoll, level=logging.DEBUG, message='Simple polling: %s' % exe)
    except Exception, e:
        print e
        raise

